<?php

namespace api\components;

use api\modules\manage\models\DictElements;
use Yii;
use yii\helpers\ArrayHelper;
use api\components\helpers\Constant;
use api\modules\app\models\MetaArea;
use api\modules\app\services\CacheService;
use yii\web\IdentityInterface;

class UserCenter implements IdentityInterface
{

    const LOGIN_BY_USERNAME_URL = "oauth/login-by-username";
    const LOGIN_BY_USERNAME_URL_NEW = 'oauth/login-by-username-new';
    const LOGIN_BY_TOKEN = "oauth/login-by-token";
    const LOGIN_BY_TOKEN_NEW = "oauth/login-by-token-new";
    const GET_USER_BY_ID = "user/get-user-by-id";
    const LOGIN_BY_WECHAT_PHONE = 'oauth/login-by-wechart';
//    const LOGIN_BY_WECHAT_ID = 'oauth/login-by-wechart-id';
    const LOGIN_BY_WECHAT_ID = 'oauth/login-by-wechart-id-new';
    const LOGOUT_BY_TOKEN = 'oauth/logout-by-token';
    const GET_USER_LIST = 'user';
    const CTEATE_USER = 'user/create';

    public $host;
    public $appId;
    public $appKey;

    public function validateAuthKey($authKey)
    {
        // TODO: Implement validateAuthKey() method.
    }

    public function getId()
    {
        // TODO: Implement getId() method.
    }

    public function getAuthKey()
    {
        // TODO: Implement getAuthKey() method.
    }

    public static function findIdentity($id)
    {
        $redis = Yii::$app->redisCache;
        $key = \api\common\helpers\Constant::LOGIN_USER_CACHE_ID . '_' . $id;
        $identity = $redis->get($key);
        return json_decode($identity, true);
    }

    public static function findIdentityByAccessToken($token, $type = null)
    {
        $redis = Yii::$app->redisCache;
        $key = \api\common\helpers\Constant::LOGIN_USER_CACHE . '_' . $token;
        $identity = $redis->get($key);
        return json_decode($identity, true);
    }

    public function getUsers($start = null, $end = null)
    {
        $baseUrl = $this->host;
        $url = $baseUrl . self::GET_USER_LIST;
        $params = [];
        if ($start && $end) {
            $params['start'] = $start;
            $params['end'] = $end;
        }
        $response = $this->_request($url, 'get', $params);
        if (ArrayHelper::getValue($response, 'error', 1) === 1) {
            $code = ArrayHelper::getValue($response, 'data.status');
            $message = ArrayHelper::getValue($response, 'data.message');
            throw new \Exception($message);
        }
        $user = $response['data'];
        return $response['data'];
    }

    public function createUsers($users = [])
    {
        $baseUrl = $this->host;
        $url = $baseUrl . self::CTEATE_USER;
        $response = $this->_request($url, 'post', [], ['data' => json_encode($users)]);
        if (ArrayHelper::getValue($response, 'error', 1) === 1) {
            $message = ArrayHelper::getValue($response, 'data.message');
            throw new \Exception($message);
        }
        return $response['data'];
    }

    private function _request($url, $method, $params = [], $body = [])
    {
        $method = strtolower($method);
        $timestamp = time();
        $sign = $this->generateSign($this->appId, $this->appKey, $timestamp);
        $_params = [
            'appId' => $this->appId,
            'timestamp' => $timestamp,
            'sign' => $sign
        ];
        $params = array_merge($params, $_params);
        $url = $url . '?' . http_build_query($params);
        if ($method === 'get') {
            $response = $this->request($url, 'GET');
        } else {
            $response = $this->request($url, 'POST', $body);
        }
        $response = json_decode($response, true);
        return $response;
    }

    public function loginByUsername($username, $password)
    {
        $baseUrl = $this->host;
        $url = $baseUrl . self::LOGIN_BY_USERNAME_URL;
        $timestamp = time();
        $sign = $this->generateSign($this->appId, $this->appKey, $timestamp);
        $params = [
            'appId' => $this->appId,
            'timestamp' => $timestamp,
            'sign' => $sign
        ];
        $url = $url . '?' . http_build_query($params);
        $response = $this->request($url, 'POST', ['username' => $username, 'password' => $password]);
        $response = json_decode($response, true);
        if (ArrayHelper::getValue($response, 'error', 1) === 1) {
            $code = ArrayHelper::getValue($response, 'data.status');
            $message = ArrayHelper::getValue($response, 'data.message', "登录失败");
            $result = ['code' => $code, 'message' => $message, 'status' => Constant::API_STATUS_FAILED];
            Yii::$app->response->data = $result;
            Yii::$app->response->send();
            Yii::$app->end();
        }
        return $response['data'];
    }

    public function loginByUsernameNew($username, $password)
    {
        $baseUrl = $this->host;
        $url = $baseUrl . self::LOGIN_BY_USERNAME_URL_NEW;
        $timestamp = time();
        $sign = $this->generateSign($this->appId, $this->appKey, $timestamp);
        $params = [
            'appId' => $this->appId,
            'timestamp' => $timestamp,
            'sign' => $sign
        ];
        $url = $url . '?' . http_build_query($params);
        $response = $this->request($url, 'POST', ['username' => $username, 'password' => $password]);
        $response = json_decode($response, true);
        if (ArrayHelper::getValue($response, 'error', 1) === 1) {
            $code = ArrayHelper::getValue($response, 'data.status');
            $message = ArrayHelper::getValue($response, 'data.message', "登录失败");
            $result = ['code' => $code, 'message' => $message, 'status' => Constant::API_STATUS_FAILED];
            Yii::$app->response->data = $result;
            Yii::$app->response->send();
            Yii::$app->end();
        }
        return $response['data'];
    }

    public function loginByToken($token)
    {
        $baseUrl = $this->host;
        $url = $baseUrl . self::LOGIN_BY_TOKEN;
        $timestamp = time();
        $sign = $this->generateSign($this->appId, $this->appKey, $timestamp);
        $params = [
            'appId' => $this->appId,
            'timestamp' => $timestamp,
            'sign' => $sign
        ];
        $url = $url . '?' . http_build_query($params);
        $response = $this->request($url, 'POST', ['accessToken' => $token]);
        $response = json_decode($response, true);
        if (ArrayHelper::getValue($response, 'error', 1) === 1) {
            return false;
        }
        $user = $response['data'];
        return $user;
    }

    public function loginByTokenNew($token)
    {
        $baseUrl = $this->host;
        $url = $baseUrl . self::LOGIN_BY_TOKEN_NEW;
        $timestamp = time();
        $sign = $this->generateSign($this->appId, $this->appKey, $timestamp);
        $params = [
            'appId' => $this->appId,
            'timestamp' => $timestamp,
            'sign' => $sign
        ];
        $url = $url . '?' . http_build_query($params);
        $response = $this->request($url, 'POST', ['accessToken' => $token]);
        $response = json_decode($response, true);
        \Yii::error('loginByTokenNew===='.json_encode([$url,$response,$token]));
        if (ArrayHelper::getValue($response, 'error', 1) === 1) {
            return false;
        }
        $user = $this->convert2OldStruct($response['data']);
        return $user;
    }

    private function convert2OldStruct($data)
    {
        return $data;
    }

    public function getUserById($userId)
    {
        $baseUrl = $this->host;
        $url = $baseUrl . self::GET_USER_BY_ID;
        $timestamp = time();
        $sign = $this->generateSign($this->appId, $this->appKey, $timestamp);
        $params = [
            'appId' => $this->appId,
            'timestamp' => $timestamp,
            'sign' => $sign,
            'id' => $userId
        ];
        $url = $url . '?' . http_build_query($params);
        $response = $this->request($url, 'GET');
        $response = json_decode($response, true);
        if (ArrayHelper::getValue($response, 'error', 1) === 1) {
            return false;
        }
        $user = $response['data'];
        return $user;
    }

    public static function getUserRights($aim, $byToken = true)
    {
        $redis = Yii::$app->redisCache;
        if ($byToken) {
            $key = \api\common\helpers\Constant::LOGIN_USER_CACHE . '_' . $aim;
        } else {
            $key = \api\common\helpers\Constant::LOGIN_USER_CACHE_ID . '_' . $aim;
        }
        $data = $redis->get($key);
        $data = json_decode($data, true);
        return $data['permission']['menu'];
    }

    public static function getUserActions($aim, $byToken = true, $menuCode = null)
    {
        // $cacheData = (new CacheService())->getUserActionByToken($aim);
        // if (!empty($cacheData)) {
        //     return $cacheData;
        // }
        $redis = Yii::$app->redisCache;
        if ($byToken) {
            $key = \api\common\helpers\Constant::LOGIN_USER_CACHE . '_' . $aim;
        } else {
            $key = \api\common\helpers\Constant::LOGIN_USER_CACHE_ID . '_' . $aim;
        }
        $data = $redis->get($key);
        $data = json_decode($data, true);
        if ($menuCode) {
            $codes = self::getAimMenuActions($data['permissionNew'], $menuCode);
            $result = $codes ? $codes : [];
        } else {
            $result = $data['permissionNew'] ?? [];
        }

        // (new CacheService())->cacheUserActionByToken($aim, $result);
        return $result;
    }

    private static function getAimMenuActions($permissions, $menuCode)
    {
        $codes = [];
        if (!empty($permissions)) {
            foreach ($permissions as $row) {
                if ($row['type'] == 1 && $row['code'] == $menuCode) {
                    if (!empty($row['children'])) {
                        foreach ($row['children'] as $item) {
                            if ($item['type'] == 2) {
                                $action = DictElements::findOne(['code' => $item['code']]);
                                $codes[] = $action;
                            }
                        }
                    }
                    return $codes;
                } else {
                    if (!empty($row['children'])) {
                        $codes = self::getAimMenuActions($row['children'], $menuCode);
                        if ($codes) {
                            return $codes;
                        }
                    }
                }
            }
        }
        return false;
    }

    public function logout($token)
    {
        $baseUrl = $this->host;
        $url = $baseUrl . self::LOGOUT_BY_TOKEN;
        $timestamp = time();
        $sign = $this->generateSign($this->appId, $this->appKey, $timestamp);
        $params = [
            'appId' => $this->appId,
            'timestamp' => $timestamp,
            'sign' => $sign
        ];
        $url = $url . '?' . http_build_query($params);
        $response = $this->request($url, 'POST', ['accessToken' => $token]);
        $response = json_decode($response, true);
        if (ArrayHelper::getValue($response, 'error', 1) === 1) {
            $message = ArrayHelper::getValue($response, 'data.message', "操作失败");
            throw new \Exception($message);
        }
        return true;
    }

    public function generateSign($appId, $appKey, $timestamp)
    {
        $signStr = "appId=%s&timestamp=%s&secret=%s";
        $signStr = sprintf($signStr, $appId, $timestamp, $appKey);
        return sha1($signStr);
    }

    public function request(string $url, string $method = "get", $params = [])
    {
        $method = strtolower($method);
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        if ($method == 'post') {
            curl_setopt($curl, CURLOPT_POST, 1); //post提交方式
            curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
        }
        $response = curl_exec($curl);
        return $response;
    }

    public function syncMetaArea()
    {
        $url = $this->host . '/meta-data/area-no-department';
        $response = $this->_request($url, 'GET');
        if ($response['error'] == 0 && count($response['data']) > 0) {
            $metaAreas = $response['data'];
            $metaAreasPieces = array_chunk($metaAreas, 200);
            try {
                foreach ($metaAreasPieces as $piece) {
                    $rows = [];
                    foreach ($piece as $row) {
                        $item = [
                            'id' => $row['id'],
                            'name' => $row['name'],
                            'address' => $row['address'],
                            'category' => $row['category'],
                            'parent_id' => $row['parent_id'],
                            'lng' => $row['lng'],
                            'lat' => $row['lat'],
                            'area_info' => '',
                            'status' => $row['status'],
                            'code' => $row['code'],
                            'polygon_gps' => '',
                            'user_id' => $row['user_id'],
                            'level' => $row['level'],
                            'route_id' => $row['route_id'],
                            'route_vice_id' => $row['route_vice_id']
                        ];
                        if ($row['category'] == '网格') {
                            $item['polygon_gps'] = '';
                        }
                        $rows[] = $item;
                    }
                    Yii::$app->test_3->createCommand()
                                     ->batchInsert(MetaArea::tableName(), array_keys($rows[0]), $rows)
                                     ->execute();
                }
            } catch (\Exception $e) {
                return $e;
            }
            return true;
        } else {
            return false;
        }
    }

    public function loginByWechatId($wechatId, $category = 'zw')
    {
        $baseUrl = $this->host;
        $url = $baseUrl . self::LOGIN_BY_WECHAT_ID;
        $timestamp = time();
        $sign = $this->generateSign($this->appId, $this->appKey, $timestamp);
        $params = [
            'appId' => $this->appId,
            'timestamp' => $timestamp,
            'sign' => $sign
        ];
        $url = $url . '?' . http_build_query($params);
        $response = $this->request($url, 'POST', ['wechart_id' => $wechatId, 'category' => $category]);
        \Yii::error('===loginbycode_wid======'.json_encode($response).'===='.$url.'==='.$wechatId);
        $response = json_decode($response, true);
        if (ArrayHelper::getValue($response, 'error', 1) === 1) {
            $message = ArrayHelper::getValue($response, 'data.message', "操作失败");
            throw new \Exception($message);
        }
        return $response;
    }

}

